package com.example.springsecuritycsrf.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class HttpServletRequestWrapFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        
    }

    private static class RequestBodyServletRequestWrapper extends HttpServletRequestWrapper{

        private final byte[] requestBody;
        private final Map<String,String[]> paramMap;
        /**
         * Constructs a request object wrapping the given request.
         *
         * @param request The request to wrap
         * @throws IllegalArgumentException if the request is null
         */
        @SneakyThrows
        public RequestBodyServletRequestWrapper(HttpServletRequest request) {
            super(request);
            requestBody = IOUtils.toByteArray(request.getReader(), StandardCharsets.UTF_8);
            paramMap = new HashMap<>();
            if (requestBody.length == 0) {
                return;
            }
            JSONObject jsonObject = JSON.parseObject(getRequestBody());
            jsonObject.forEach((key,value) -> paramMap.put(key,new String[]{String.valueOf(value)}));
        }

        public String getRequestBody(){
            return StringUtils.toEncodedString(requestBody,StandardCharsets.UTF_8);
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return paramMap;
        }

        @Override
        public String getParameter(String key) {
            String[] valueAttr = paramMap.get(key);
            if (valueAttr == null || valueAttr.length == 0) {
                return null;
            }
            return valueAttr[0];
        }

        @Override
        public String[] getParameterValues(String key) {
            return paramMap.get(key);
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return Collections.enumeration(paramMap.keySet());
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBody);
            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener listener) {

                }

                @Override
                public int read() throws IOException {
                    return inputStream.read();
                }
            };
        }

    }
}
